// main.go
package main

//import "fmt"
import (
    "fyne.io/fyne/v2"
	"fyne.io/fyne/v2/widget"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	//"fyne.io/fyne/v2/theme"
    "github.com/flopp/go-findfont"
)

import "time"

import (
	"encoding/json"
	"fmt"
	"os"
	"io"
	"io/ioutil"
	"net"
	"log"
	"flag"
	"strings"
	"strconv"
    "archive/zip"
)

var (
    config Config
    ch_trans chan bool  //定义了一个传输的管道, true = 停止
    myApp App
)

// Config 配置
type Config struct {
	Client *ClientConfig `json:"client"`
    Server *ServerConfig `json:"server"`
}

// ClientConfig 客户端配置
type ClientConfig struct {
	Name       string   `json:"name"`        // 名称
	Addr       string   `json:"addr"`        //服务端地址
}

// ServerConfig 服务端配置
type ServerConfig struct {
	Name       string   `json:"name"`        // 名称
	Port       int      `json:"port"`        //服务端口
    Sdir  string   `json:"s_dir"`            //服务器文件夹
    Cdir  string   `json:"c_dir"`            //临时接收文件夹
}


type App struct {
    App         fyne.App
    MainWindow  fyne.Window  //主界面
    TimeContainer      *fyne.Container  //时间容器, 容器才可以刷新内容
    lab_output         *widget.Label    //显示命令内容
    entry              *widget.Entry    //输入框
    //lab_res            *widget.Label    //提示框  //edit := widget.NewMultiLineEntry()
    lab_res            *widget.Entry
    start              *widget.Button
    stop               *widget.Button
}

func setFont(){  //设置中文字体
    fontPaths := findfont.List()
    for _,fontPath := range fontPaths {
        if strings.Contains(fontPath, "msyh.ttf"){
            err := os.Setenv("FYNE_FONT", fontPath)
            if err!=nil{
                return
            }
            break
        }
    }    
}


func init() {
    cfg:=flag.String("f","config.json","Config file")
	flag.Parse()

	/*  载入 配置 */
	configBytes,err:=ioutil.ReadFile(*cfg)
	if err!=nil{
		panic(err)
	}
	
	err=json.Unmarshal(configBytes,&config)
	if err!=nil{
		panic(err)
	}
}

func main() {	
	//go client()
    setFont()
    defer os.Unsetenv("FYNE_FONT")

    ch_trans = make(chan bool, 1)  //新建一个按钮
    
    a := app.New()
    myApp.App = a
    myApp.MainWindow = a.NewWindow("File Transfer Server")
    myApp.MainWindow.Resize(fyne.Size{Width: 500, Height: 500})
    myApp.makeUI()
	myApp.MainWindow.ShowAndRun()
}


func (app *App) makeUI() {
    

    
        //中断是按钮
    //btn_pause := widget.NewButtonWithIcon("Pause", theme.HomeIcon(), func(){
//     btn_pause: = widget.NewButton("Pause", func(){
//         app.lab_res.SetText("Pause")
//         //ch_trans <- true
//     })
    //btn_pause.Importance = widget.HighImportance
    //btn_pause.Disabled()
    

    
    lab_output := widget.NewLabel("File Transfer Software!")  //提示框
    lab_res := widget.NewMultiLineEntry()  
    scroll := container.NewScroll(lab_res)
    
    scroll.SetMinSize(fyne.Size{
        Width: 500,
        Height: 250,
        
    })
    
    lab_time := widget.NewLabel(get_time())  //时间框
    entry := widget.NewEntry()  //输入框
    
    
    /* 2个互斥的按钮 */

	app.start = widget.NewButton("start", func() {
		app.start.Disable()
		app.stop.Enable()
        go app.client(entry.Text)
	})
	app.stop = widget.NewButton("stop", func() {
		app.start.Enable()
		app.stop.Disable()
        app.lab_res.SetText("Pause")
        ch_trans <- true
        
	})
	app.stop.Disable()
	// 水平布局
	cc := container.NewHBox(
		app.start,
		app.stop,
	)
    /* end */
    
    
    //发送
    btn_start := widget.NewButton("Send", func() {  //button的回调函数
        //app.lab_output.SetText(entry.Text)  //entry.Text
        go app.client(entry.Text)
    })
    btn_start.Importance = widget.HighImportance
    
    //清除
    btn_stop := widget.NewButton("Clear", func() {  //button的回调函数
        //app.lab_output.SetText("Stop...")
        app.entry.SetText("")
        app.lab_res.SetText("")
        
        app.start.Enable()
		app.stop.Disable()
    })
    btn_stop.Importance = widget.HighImportance
        
    //选择文件
    btn_file := widget.NewButton("Choose File", app.openFunc(app.MainWindow))
    btn_file.Importance = widget.HighImportance
    

    
    //续传
//     btn_pause := widget.NewButton("Continue", func(){
//         app.lab_res.SetText("Continue")
//         ch_trans <- true
//     })
//     btn_pause.Importance = widget.HighImportance
    
    app.lab_output = lab_output  //传递一个指针过来，可以改变label的值
    app.lab_res = lab_res
    app.entry = entry
    
    timeContainer := container.NewGridWithColumns(1,   //时间容器里放入时间框
        lab_time,
    )
    
    app.TimeContainer = timeContainer  //对时间框进行装配
    
    
    
    //app.lab_time = lab_time
    
    finalContent := container.NewVBox(cc,lab_output,timeContainer, entry, btn_start, btn_stop, btn_file,scroll)  //装配
    app.MainWindow.SetContent(finalContent)  //将装配后的container放入mainwindow
    
	go func() {
		for range time.Tick(time.Second * 1) {  //30秒刷新
			app.refreshTime()
            //app.lab_time = widget.NewLabel(get_time())
		}
	}()
 
}

//选择发送文件
func (app *App) openFunc(win fyne.Window) func() {
	return func(){
		openDialog := dialog.NewFileOpen(func(read fyne.URIReadCloser,err error){
			if err != nil{
				dialog.ShowError(err, win)
				return
			}

			if read == nil{
				return
			}

			defer read.Close()

// 			data, err := ioutil.ReadAll(read)
// 			if err!=nil{
// 				dialog.ShowError(err,win)
// 				return 
// 			}

			//app.EditWidget.SetText(string(data))
            //app.lab_output.SetText(string(data))
			//app.CurrentFile = read.URI()

			//win.SetTitle(win.Title() + " - " + read.URI().Name())
            app.entry.SetText(read.URI().Path())
			//app.SaveMenuItem.Disabled = false 

		}, win)

		//openDialog.SetFilter(filter)
		openDialog.Show()
		
	}
}

func get_time() string {
    return time.Now().Format("2006-01-02 15:04:05")
}

func (app *App) refreshTime() {
    lab_time := widget.NewLabel(get_time())
    app.TimeContainer.Objects = []fyne.CanvasObject{lab_time}
    app.TimeContainer.Refresh()   //容器刷新
}

func (app *App) client(path string) {
    
    if path == "get" {  //get为得到清单
        //app.lab_output.SetText("get command")
        log.Println("get")
        app.send_conn("get")
        
    } else if len(path) > 4 && path[:4] == "get|"{  //下载某个文件
        fileName := strings.Split(path, "|")[1]
        log.Println("get|", fileName)
        app.send_conn("get|" + fileName)
                
    } else if len(path) > 4 && path[:4] == "del|"{  //删除某个文件
        fileName := strings.Split(path, "|")[1]
        log.Println("del|", fileName)
        app.send_conn("del|" + fileName)
    } else if len(path) > 7 && path[:7] == "rename|"{  // 改名
        log.Println(path)
        app.send_conn(path) 
    } else if len(path) > 6 && path[:6] == "mkdir|"{  // 改名
        log.Println(path)
        app.send_conn(path)  
    } else if path == "getall" {  //得到所以文件的一个完整压缩包
        log.Println("getall")
        app.send_conn("getall")
                
    } else { //发送文件
                if !Exists(path) {  //如果文件/文件夹不存在
                    app.lab_res.SetText("file not exist")
                    log.Println("文件/文件夹不存在")
                    return
                    
                } else {
                    if IsFile(path) {  //如果是文件
                        log.Println("发送文件...")
                        
                        app.lab_res.SetText("send file...")
                        info, err:=os.Stat(path)
                        if err!=nil{
                            log.Println(err)
                            return
                        }
                        log.Println("文件名: ", info.Name())
                        log.Println("文件大小: ", info.Size() / 1024 / 1024, "MB")
                        
                        conn, err:=net.Dial("tcp", config.Client.Addr)
                        if err!=nil{
                            fmt.Println(err)
                            return
                        }
                        
                        log.Println("连接服务器成功!")
                        
                        defer conn.Close()

                        s_info := info.Name() + "|" + fmt.Sprintf("%d", info.Size())  //1.txt|1234
                        log.Println("发送命令 ", s_info)
                        _,err=conn.Write([]byte(s_info))
                        if err!=nil{
                            fmt.Println(err)
                            return
                        }
                        
                        var n int
                        buf := make([]byte, 1024)
                        n,err=conn.Read(buf)
                        if err!=nil{
                            fmt.Println(err)
                            return
                        }
                        
                        if "ok" == string(buf[:n]) {
                            //send file
                            log.Println("发送中...")
                            app.SendFile(path, conn)
                        }
                        log.Println("断开连接")
                        
                        
                    } else if IsDir(path) {  //如果是文件夹
                        log.Println("发送文件夹...")
                        app.SendDir(path)
                        
                    } else {    //todo

                    }
                }
    }
    
}

func (app *App) send_conn(command string){
        conn, err:=net.Dial("tcp", config.Client.Addr)
        if err!=nil{
            log.Println(err)
            return
        }
        log.Println("连接服务器成功!")
        
        defer conn.Close()
        
        if command == "get" {  //拿到目录列表
            _,err=conn.Write([]byte(command))
            if err!=nil{
                log.Println(err)
                return
            }
            
            //如果是get 仅仅返回数据列表
            var n int
            var list string
            buf := make([]byte, 1024)
            for {
                n,err=conn.Read(buf)
                if err != nil{
                    if err == io.EOF {
                        //log.Println("文件夹为空...")
                        
                    }else{
                        log.Println(err)
                        
                    }
                    break
                }
                list = list + string(buf[:n])
            }

            
            app.lab_res.SetText(list)
            
        } else if len(command) > 4 && command[:4] == "get|" {  //发服务器发送get文件请求

            _,err=conn.Write([]byte(command))
            if err!=nil{
                fmt.Println(err)
                return
            }
            
            
            log.Println("正在接收数据...")
            
            
            buf := make([]byte, 1024)
            
            for {
                n, err := conn.Read(buf) //读取对方发送的文件名
                if err != nil{
                    if err == io.EOF {  //如果接收到文件末
                        //log.Println("接收到EOF")
                        break
                    } else {
                        log.Println("接收到错误")
                        fmt.Println(err)
                        return
                    }
                    
                    
                }
                fileName := string(buf[:n])
                log.Println("接收到的信息: ", fileName)
                if "nofile" == fileName {
                    log.Println("文件/文件夹不存在")
                    app.lab_res.SetText("服务器端 文件/文件夹不存在")
                    return
                }
                
                log.Println("向客户端发送ok")
                conn.Write([]byte("ok"))
                
                log.Println("接收中...")
                
                /*      以下处理接收文件    */
                app.RecvFile(fileName, conn)
                /*       end               */
                
                //log.Println(fileName, "接收完毕")
                
                //app.lab_res.SetText(fileName + "接收完毕")
            }

        } else if len(command) > 4 && command[:4] == "del|" {  //发服务器发送del

            app.Action(command, conn)
            
        } else if len(command) > 7 && command[:7] == "rename|" {  //发服务器发送rename

            app.Action(command, conn)
        } else if len(command) > 6 && command[:6] == "mkdir|" {  //发服务器发送
            
            app.Action(command, conn)
        } else if command == "getall" {  //传输整个目录
            
            _,err=conn.Write([]byte(command))
            if err!=nil{
                log.Println(err)
                return
            }
            
            
            app.lab_res.SetText("receive data ...")
            
            
            buf := make([]byte, 1024)
            
            for {
                n, err := conn.Read(buf) //读取对方发送的文件名
                if err != nil{
                    if err == io.EOF {  //如果接收到文件末
                        //log.Println("接收到EOF")
                        break
                    } else {
                        app.lab_res.SetText("receive error")
                        log.Println(err)
                        return
                    }
                    
                    
                }
                fileName := string(buf[:n])
                log.Println("接收到的信息: ", fileName)
                
                
                log.Println("向客户端发送ok")
                conn.Write([]byte("ok"))
                
                log.Println("接收中...")
                
                
                /*      以下处理接收文件    */
                app.RecvFile(fileName, conn)
                /*       end               */
                
                log.Println(fileName, "接收完毕3...开始解压缩...")
                app.lab_res.SetText("begin to uncompress")
                
                
                if err1 := DeCompress(config.Server.Cdir + fileName, config.Server.Cdir); err1 != nil {
                    log.Println("解压缩错误...")
                    log.Println(err1)
                } else {
                    log.Println("解压成功....")
                    app.lab_res.SetText("receive success!")
                }
                
                
            }

        }

        log.Println("断开连接")
}

func (app *App) Action(command string, conn net.Conn) error {
    _,err := conn.Write([]byte(command))
    if err!=nil{
        fmt.Println(err)
        return err
    }
    log.Println("正在接收数据...")
    buf := make([]byte, 1024)
    for {
        n, err := conn.Read(buf) //读取对方发送的结果
        if err != nil{
            if err == io.EOF {  //如果接收到文件末
                //log.Println("接收到EOF")
                break
            } else {
                log.Println("接收到错误")
                fmt.Println(err)
                return err
            }
            
            
        }
        fileName := string(buf[:n])
        log.Println("接收到的信息: ", fileName)
        if "nofile" == fileName {
            log.Println("服务器端 文件/文件夹不存在")
            app.lab_res.SetText("服务器端 文件/文件夹不存在")
            return nil
        }
        log.Println(fileName)
        app.lab_res.SetText(fileName)
    }
    return nil
}

// 发送文件夹
func (app *App) SendDir(path string){
    
    fs,_:= ioutil.ReadDir(path)
    for _,file:=range fs{
        if file.IsDir(){  //如果是文件夹, 继续往下搜
            fmt.Println(path+file.Name())
            app.SendDir(path+file.Name()+"/")  //递归
            //getFileList(path+file.Name()+"/")
        }else{
            fmt.Println(path+file.Name())
            pathFile := path+file.Name()
            
            //todo
            
            info, err:=os.Stat(pathFile)
            if err!=nil{
                fmt.Println(err)
                continue
            }
            log.Println("文件名: ", info.Name())
            log.Println("文件大小: ", info.Size() / 1024 , "KB")
            
            
            conn, err:=net.Dial("tcp", config.Client.Addr)
            if err!=nil{
                fmt.Println(err)
                continue
            }
            
            log.Println("连接服务器成功!")
            defer conn.Close()
            
            
            _,err=conn.Write([]byte(info.Name()))
            if err!=nil{
                fmt.Println(err)
                continue
            }
            
            var n int
            buf := make([]byte, 1024)
            n,err=conn.Read(buf)
            if err!=nil{
                fmt.Println(err)
                continue
            }
            
            if "ok" == string(buf[:n]) {
                //send file
                log.Println("发送中...")
                app.SendFile(pathFile, conn)
            }

        }
    }

    

}

// 发送文件
func (app *App) SendFile(path string, conn net.Conn){
    f,err:=os.Open(path)
    if err!=nil{
        fmt.Println(err)
        return
    }
    defer f.Close()

    info, err:=os.Stat(path)
    if err!=nil{
        log.Println(err)
        return
    }
    fileSize := int(info.Size())
    //fileSize, _ := strconv.ParseInt(info.Size(),10,64)
    
    /* 新增 续传功能 */
    srcFile := path 
    destFile := srcFile[strings.LastIndex(srcFile, "/")+1:]  //从D:/1.txt里取1.txt
    tempFile := destFile + "temp.txt"  //1.txt => 1.txttemp.txt
    fmt.Println("生成临时文件: ", tempFile)
    file3, err := os.OpenFile(tempFile, os.O_CREATE | os.O_RDWR, os.ModePerm)
    if err != nil {
        return
    }

    //step1
    file3.Seek(0, io.SeekStart)
    bs := make([]byte, 100, 100)
    n1, err:=file3.Read(bs)
    //HandleErr(err)
    countStr:=string(bs[:n1])
    count, err:=strconv.ParseInt(countStr, 10,64)
    //HandleErr(err)
    fmt.Println("count:", count)
    
    //step2
    f.Seek(count, io.SeekStart)  //这一步定位到上次断开的地方
    n :=-1
    total:=int(count)
    /* 新增 end*/
    
    buf := make([]byte, 1024*4)  //造一个4096大小的切片
    for {
        select {
            case <- ch_trans:  //中断传输信号
                log.Println("中断传输")
                fmt.Println("暂停传输 已传输 total:", total)
                return
            
            default:  //没有收到中断信号 默认为发送文件
            
                n,err =f.Read(buf)  //*修改
                if err!=nil{
                    if err == io.EOF {
                        conn.Close()
                        log.Println("发送完毕send over ", total)
                        //myApp.lab_res.SetText("发送完毕" + strconv.Itoa(total))

                        
                        file3.Close()  //*新增
                        os.Remove(tempFile)  //*新增
                        
                        app.start.Enable()
                        app.stop.Disable()
                        
                    }else{
                        fmt.Println(err)
                    }
                    return
                }
                
                conn.Write(buf[:n])

                

                /* 新增 */
                total+=n
                file3.Seek(0, io.SeekStart)
                file3.WriteString(strconv.Itoa(total))
                
                left, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", float64(total) / float64(fileSize)), 64)  //0.43
                left = left * 100
                app.lab_res.SetText("send file..." + strconv.Itoa(total) + "/" + strconv.Itoa(fileSize) +  "(" + strconv.FormatFloat(left, 'f', -1, 64) + "%)")
                
                //app.lab_res.SetText("send file..." + strconv.Itoa(total))
                //fmt.Println("total", total)
                /* 新增 end */

                // if total > 1000 {  //模拟断电
                //     panic("duan dian")
                // }
            
        }

        
        
    }
    
}

// 判断所给路径文件/文件夹是否存在 
func Exists(path string) bool {  
    _, err := os.Stat(path)    //os.Stat获取文件信息  
    if err != nil {  
        if os.IsExist(err) {  
            return true  
        }  
        return false  
    }  
    return true  
} 

// 判断所给路径是否为文件夹  
func IsDir(path string) bool {  
    s, err := os.Stat(path)  
    if err != nil {  
        return false  
    }  
    return s.IsDir()  
}  
  
// 判断所给路径是否为文件  
func IsFile(path string) bool {  
    return !IsDir(path)  
}



//接收一个文件
func (app *App) RecvFile(fileName string, conn net.Conn)(){
    
    /* handle 兼容 1.txt  1.txt|1234 两种格式 */
    var _fileName, _fileSize string
    if strings.Index(fileName, "|") == -1 {
        _fileName = fileName
        _fileSize = "0"
    }else{
        _fileName = strings.Split(fileName, "|")[0]
        _fileSize = strings.Split(fileName, "|")[1]
    }
    fileSize,_ := strconv.Atoi(_fileSize)
    /* handle end */
    
	//file:=handle_filename(fileName)  //改名
	file:=_fileName
	log.Println(file)
    log.Println(fileSize)
    CreateDir(config.Server.Cdir)  //如果有没接收文件夹就创建文件夹
    //new
    f,err:=os.Create(config.Server.Cdir + file)
    if err!=nil{
        fmt.Println("创建文件夹失败")
        fmt.Println(err)
        return
    }
    buf := make([]byte, 1024*4)
    //total := 0
    
    /* 新增 */
    tempFile := file + "temp.txt"
    fmt.Println("生成临时文件: ", tempFile)
    file3, err := os.OpenFile(tempFile, os.O_CREATE | os.O_RDWR, os.ModePerm)
    if err != nil {
        return
    }

    //step1
	file3.Seek(0, io.SeekStart)
	bs := make([]byte, 100, 100)
	n1, err:=file3.Read(bs)
	//HandleErr(err)
	countStr:=string(bs[:n1])
	count, err:=strconv.ParseInt(countStr, 10,64)
	//HandleErr(err)
    fmt.Println(count)
    
    //step2
	f.Seek(count, io.SeekStart)
	n :=-1
	total:=int(count)
    /* 新增 end*/
    
    for {
		// ReadByte(conn, func(data []byte){
		// 	//code
		// 	log.Println("start readbyte")
		// }).callback(func(){
		// 	//callbak
		// 	log.Println("end readbyte")
		// })
        
        select {
            case <- ch_trans:
                log.Println("接收 中断传输")
                app.lab_res.SetText("接收 暂停传输 已传输 total:" + strconv.Itoa(total))
                //向服务器发送暂时请求
                conn.Write([]byte("pause"))
                //
                
                //conn.Close()
                //return
            default:
            
                n, err=conn.Read(buf)
                if err != nil{
                    
                    if err == io.EOF {
                        log.Println(fileName, "接收完毕!")
                    }else{
                        log.Println(err)
                    }
                    f.Close()  //注意文件要关闭
                    
                    file3.Close()  //新增
                    if total == fileSize {  //如果文件大小发送完毕就删除临时文件
                        os.Remove(tempFile)  //新增
                        app.start.Enable()
                        app.stop.Disable()
                    }
                    
                    //app.lab_res.SetText("接收完毕" + strconv.Itoa(total))
                    
                    return
                }
                if n == 0 {
                    fmt.Println("n==0文件接收完毕")
                    f.Close()  //注意文件要关闭
                    
                    file3.Close()  //新增
                    if total == fileSize {  //如果文件大小发送完毕就删除临时文件
                        os.Remove(tempFile)  //新增
                    }
                    
                    return
                } else {
                    //fmt.Println(n, i)
                }
                if _, err := f.Write(buf[:n]); err != nil {
                    fmt.Println(err)
                    return
                }

                /* 新增 */
                total+=n
                file3.Seek(0, io.SeekStart)
                file3.WriteString(strconv.Itoa(total))
                //fmt.Println("total", total)
                /* 新增 end */
                
                left, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", float64(total) / float64(fileSize)), 64)  //0.43
                left = left * 100
                app.lab_res.SetText("receiving..." + strconv.Itoa(total) + "/" + strconv.Itoa(fileSize) +  "(" + strconv.FormatFloat(left, 'f', -1, 64) + "%)")
            
        }

        
    }
    //fmt.Println("recv...")
    
}

//压缩文件
//src 可以是不同dir下的文件或者文件夹
//dest 压缩文件存放地址
func Compress(src string, dest string) error {
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	files := []*os.File{f}
	d, _ := os.Create(dest)
	defer d.Close()
	w := zip.NewWriter(d)
	defer w.Close()
	for _, file := range files {
		err := compress(file, "", w)
		if err != nil {
			return err
		}
	}
	return nil
}
 
func compress(file *os.File, prefix string, zw *zip.Writer) error {
	info, err := file.Stat()
	if err != nil {
		return err
	}
	if info.IsDir() {
		prefix = prefix + "/" + info.Name()
		fileInfos, err := file.Readdir(-1)
		if err != nil {
			return err
		}
		// 增加对空目录的判断
		if len(fileInfos) <= 0 {
			header, err := zip.FileInfoHeader(info)
			header.Name = prefix
			if err != nil {
				fmt.Println("error is:"+err.Error())
				return err
			}
			_, err = zw.CreateHeader(header)
			if err != nil {
				fmt.Println("create error is:"+err.Error())
				return err
			}
			file.Close()
		}
		for _, fi := range fileInfos {
			f, err := os.Open(file.Name() + "/" + fi.Name())
			if err != nil {
				return err
			}
			err = compress(f, prefix, zw)
			if err != nil {
				return err
			}
		}
	} else {
		header, err := zip.FileInfoHeader(info)
		header.Name = prefix + "/" + header.Name
		if err != nil {
			return err
		}
		writer, err := zw.CreateHeader(header)
		if err != nil {
			return err
		}
		_, err = io.Copy(writer, file)
		file.Close()
		if err != nil {
			return err
		}
	}
	return nil
}
 
//解压
func DeCompress(zipFile, dest string) error {
	reader, err := zip.OpenReader(zipFile)
	if err != nil {
		return err
	}
	defer reader.Close()
	for _, file := range reader.File {
		rc, err := file.Open()
		if err != nil {
			return err
		}
		defer rc.Close()
		filename := dest + file.Name
		err = os.MkdirAll(getDir(filename), 0755)
		if err != nil {
			return err
		}
		w, err := os.Create(filename)
		if err != nil {
			return err
		}
		defer w.Close()
		_, err = io.Copy(w, rc)
		if err != nil {
			return err
		}
		w.Close()
		rc.Close()
	}
	return nil
}
 
func getDir(path string) string {
	return subString(path, 0, strings.LastIndex(path, "/"))
}
 
func subString(str string, start, end int) string {
	rs := []rune(str)
	length := len(rs)
 
	if start < 0 || start > length {
		panic("start is wrong")
	}
 
	if end < start || end > length {
		panic("end is wrong")
	}
 
	return string(rs[start:end])
}

//判断文件夹是否存在  存在就返回true
func HasDir(path string) (bool, error) {
    _, _err := os.Stat(path)
    if _err == nil {
        return true, nil
    }
    if os.IsNotExist(_err) {
        return false, nil
    }
    return false, _err
}

//创建文件夹
func CreateDir(path string) {
    exist, err := HasDir(path)
    if err != nil {
        fmt.Printf("获取文件夹异常 -> %v\n", err)
        return
    }
    if exist {
        //fmt.Println("文件夹已存在！")
    } else {
        err := os.Mkdir(path, os.ModePerm)
        if err != nil {
            fmt.Printf("创建目录异常 -> %v\n", err)
        } else {
            fmt.Println("创建成功!")
        }
    }
}